using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.IO;
using System.Drawing;
using Styx;
using Styx.Combat.CombatRoutine;
using Styx.Helpers;
using Styx.Logic;
using Styx.Logic.Combat;
using Styx.Logic.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using TreeSharp;

namespace Plagueheart
{
    class Classname : CombatRoutine
    {
        public override sealed string Name { get { return "Plagueheart v1.1"; } }
        public override WoWClass Class { get { return WoWClass.Warlock; } }
        private static LocalPlayer Me { get { return ObjectManager.Me; } }

		public DateTime _ISF = DateTime.Now;
		public DateTime _immo = DateTime.Now;
		public static WoWSpell immo = WoWSpell.FromId(348);
		public static WoWSpell ImpSF = WoWSpell.FromId(85383);
		public static WoWSpell Shaddar = WoWSpell.FromId(6353);

		List<Stopwatch> debuffCooldowns;
		Stopwatch _corruption = new Stopwatch();
		Stopwatch _doom = new Stopwatch();
		Stopwatch _agony = new Stopwatch();
		
   
        #region Log
        private void slog(string format, params object[] args) //use for slogging
        {
            Logging.Write(format, args);
        }
        #endregion
        

        #region Initialize
        public override void Initialize()
        {
			Logging.Write(Color.White, "___________________________________________________");
            Logging.Write(Color.Crimson, "-------- Plagueheart v1.1 CC by Shaddar -------");
			Logging.Write(Color.Crimson, "-----  Remember to comment on the forum! --");
			Logging.Write(Color.Crimson, "-------- /like and +rep if you like this CC! ------");
			Logging.Write(Color.White, "___________________________________________________");
        }
        #endregion

        #region Settings

        public override bool WantButton
        {
            get
            {
                return true;
            }
        }

        public override void OnButtonPress()
        {
            Logging.Write(Color.Aqua, "No need to configure anything!");
        }
        #endregion

		#region StopWatch

		public override void Pulse()
		{
            if (debuffCooldowns == null)
            {
                debuffCooldowns = new List<Stopwatch>();
				debuffCooldowns.Add(_corruption);
				debuffCooldowns.Add(_doom);
				debuffCooldowns.Add(_agony);
				
            }
		}

		#endregion

		#region Rest

        public override bool NeedRest
        {
            get
            {
                if (!Me.Mounted && CastBuff("Fel Armor"))
					if(CastSpell("Fel Armor")==true)
					Thread.Sleep(7000);
                    

				if (!Me.Mounted && !Me.GotAlivePet) 
					Lua.DoString("RunMacroText('/cast Summon Imp');");
					Thread.Sleep(1000);

                if (Me.Pet.IsAlive && !Me.Mounted && !Me.HasAura("Dark Intent"))
					Lua.DoString("RunMacroText('/cast [@target,exists][@pet][] Dark Intent');");
                    Thread.Sleep(1000);

				if (Me.ManaPercent < 50 || Me.HealthPercent < 50 || Me.CurrentSoulShards < 3)
					if(CastSpell("Soul Harvest"));

                return false;
            }
        }

        public override void Rest()
		{

		}
        #endregion

		#region AOE
		public static bool Cast(string spellName, WoWPoint MeCurrentTargetLocation)
		{

		bool result = SpellManager.Cast(spellName);
		LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
		return result;

		}  
		#endregion

		#region Add Detection
        //Credit to CodeNameGamma for detectAdds code
        private List<WoWUnit> adds = new List<WoWUnit>();

		private List<WoWUnit> detectAdds()
        {
            if (Me.CurrentTarget != null)
            {
                List<WoWUnit> addList = ObjectManager.GetObjectsOfType<WoWUnit>(false).FindAll(unit =>
                            unit.Guid != Me.Guid &&
                            unit.Location.Distance(Me.CurrentTarget.Location) <= 10 &&
							(unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember || unit.IsTargetingMeOrPet) &&
                            !unit.IsFriendly &&
                            !unit.IsPet &&
                            !Styx.Logic.Blacklist.Contains(unit.Guid));

                if (addList.Count > 1)
                {
                    Logging.Write(Color.Crimson, "Detected " + addList.Count.ToString() + " adds! Switchting to AoE mode!");
                }
                return addList;
            }
            else
            {
                return null;
            }
            
        }  
		private bool IsTargetBoss()
        {
            string UnitClassification = Lua.GetReturnValues("local classification = UnitClassification(\"target\"); return classification")[0];
            string UnitLevel = Lua.GetReturnValues("local level = UnitLevel(\"target\"); return level")[0];
            if (!Me.IsInRaid)
            {
                if (UnitClassification == "worldboss" ||
                   (Me.CurrentTarget.Level == 89 && Me.CurrentTarget.Elite) ||
                   (Me.CurrentTarget.Level == 90))
                    return true;

                else return false;
            }
            else
            {
                if (UnitLevel == "-1")
                    return true;

                else return false;
            }
            
            
        }
        #endregion

		#region ISF
       
        private bool ISF()
        {
			if (Me.HasAura("Empowered Imp"))
            {
				return true;
			}
			
            if (Me.Auras.ContainsKey("Improved Soul Fire"))
            {
                var auras = Me.GetAllAuras();
                foreach (var a in auras)
                {
                  
                    if (a.SpellId == ImpSF.Id)
                    {
                        
                        if (a.TimeLeft.TotalMilliseconds < (Shaddar.CastTime + (Me.CurrentTarget.Distance * 45) + 1000))
                        {
                            return true;
                        }
						else
						{
							return false;
						}
                    }
                }
            }
            
            return true;
        }
        #endregion

        #region CastSpell Method
        // Credit to Apoc for the below CastSpell code
        // Used for calling CastSpell in the Combat Rotation
        public bool CastSpell(string spellName)
        {
            if (SpellManager.CanCast(spellName))
            {
                SpellManager.Cast(spellName);
                // We managed to cast the spell, so return true, saying we were able to cast it.
                return true;
            }
            // Can't cast the spell right now, so return false.
            return false;
        }
		public bool CastBuff(string name)
        {
            if (!PlayerHasBuff(name) && SpellManager.CanBuff(name, Me))
            {
                SpellManager.Cast(name);
                slog(name);
                return true;
            }
            return false;
        }

        public bool PlayerHasBuff(string name)
        {
            return PlayerBuffTimeLeft(name) > 0;
        }

        public bool TargetHasDebuff(string name)
        {
            return TargetDebuffTimeLeft(name) != 0; // <0 means passive aura; >0 means active one
        }
		public double PlayerBuffTimeLeft(string name)
        {
            try
            {
                var lua = string.Format("local x=select(7, UnitBuff('player', \"{0}\", nil, 'PLAYER')); if x==nil then return 0 else return x-GetTime() end", Lua.Escape(name));
                var t = double.Parse(Lua.GetReturnValues(lua)[0]);
                return t;
            }
            catch
            {
                slog("Lua failed in AuraTimeLeft");
                return 999999;
            }
        }

        private double TargetDebuffTimeLeft(string DebuffName)
        {
            return double.Parse(Lua.GetReturnValues(string.Format("local expirationTime = select(7, UnitDebuff(\"target\", \"{0}\", nil, \"player\")); " +
                                     "if expirationTime == nil then return 0 else return expirationTime - GetTime() end", DebuffName))[0]);
        }

        public double TargetDebuffTimeLeftAll(string name)
        {
            try
            {
                var lua = string.Format("local x=select(7, UnitDebuff(\"target\", \"{0}\", nil)); if x==nil then return 0 else return x-GetTime() end", Lua.Escape(name));
                var t = double.Parse(Lua.GetReturnValues(lua)[0]);
                return t;
            }
            catch
            {
                slog("Lua failed in TargetAuraTimeLeft");
                return 999999;
            }
        }
		#endregion

        #region CombatStart


        private void AutoAttack()
        {
            if (!Me.IsAutoAttacking)
            {
                Lua.DoString("StartAttack()");
            }
        }
        #endregion

        #region Combat
      
        public override void Combat()
        {
            adds = detectAdds();
			foreach(Stopwatch s in debuffCooldowns)
            {
                if (s.Elapsed.Milliseconds >= 300)
                {
                    s.Stop();
                    s.Reset();
                }
            }
			if (Me.CurrentTarget != null  && Me.CurrentTarget.IsAlive == true && Me.Mounted == false && !(Me.ChanneledCastingSpellId == 5740))
            {


//////////////////////////////////////////////Cooldowns are here//////////////////////////////////////////////////////////////////////////////////////////////////
					
					{
					if (IsTargetBoss() && PlayerBuffTimeLeft("Improved Soul Fire") <=4)
						if (CastSpell("Soulburn"));
					}
					{
					if (IsTargetBoss() && TargetHasDebuff("Bane of Doom") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption") ||
						IsTargetBoss() && TargetHasDebuff("Bane of Agony") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption"))
						if (CastSpell("Demon Soul"));
					}
					{
					if (IsTargetBoss() && TargetHasDebuff("Bane of Doom") || IsTargetBoss() && TargetHasDebuff("Bane of Agony"))
						if (CastSpell("Summon Doomguard"));
					}
					{
					if (IsTargetBoss())
						{
						Lua.DoString("RunMacroText('/use 10');");
						}
					}
					{
					if (IsTargetBoss())
						{
						Lua.DoString("RunMacroText('/use 13');");
						}
					}
					{
					if (IsTargetBoss())
						{
						Lua.DoString("RunMacroText('/use 14');");
						}
					}

//////////////////////////////////////////////Racial Skills here//////////////////////////////////////////////////////////////////////////////////////////////////
					
					{
					if (IsTargetBoss())
						{	
						Lua.DoString("RunMacroText('/Cast Berserking');");
						}
					}
					{
					if (IsTargetBoss())
						{	
						Lua.DoString("RunMacroText('/Cast Blood Fury');");
						}
					}

///////////////////////////////////////////////AoE Rotation here//////////////////////////////////////////////////////////////////////////////////////////////////
					
					{
					if (adds.Count > 2 && Me.CurrentTarget.Distance <= 10 && Me.IsCasting==false)
						if (CastSpell("Shadowflame") == true)
							Logging.Write(Color.Red, ">> Shadowflame <<"); 
					}
					{				
					if (!Me.IsMoving && adds.Count > 5 && SpellManager.Spells["Shadowfury"].CooldownTimeLeft.TotalMilliseconds > 1000)
						{
						Lua.DoString("CastSpellByName('Rain of Fire');");
						LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
						}
					}
					{
					if (adds.Count > 2 && (!SpellManager.Spells["Shadowfury"].Cooldown) && Me.IsCasting==false)
						{
						Lua.DoString("CastSpellByName('Shadowfury');");
						LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location); 
						}
					}

///////////////////////////////////////////Single Target DPS here/////////////////////////////////////////////////////////////////////////////////////////////////
					
					{
					if(PlayerHasBuff("Empowered Imp") || PlayerHasBuff("Soulburn"))
						{
						Lua.DoString(String.Format("RunMacroText(\"/use Soul Fire\")"));
						}
					}
					{
					if (ISF() && _ISF.AddMilliseconds(Shaddar.CastTime + (Me.CurrentTarget.Distance * 45) + 700 ) < DateTime.Now)
						{
						_ISF = DateTime.Now;
						if (CastSpell("Soul Fire"));                
						return;
						}
					}
					{
					if (TargetDebuffTimeLeft("Immolate") <3)
								{
									if (_immo.AddMilliseconds(immo.CastTime + 700) < DateTime.Now)
									{
										_immo = DateTime.Now;
										if (CastSpell("Immolate"));
										return;
									}
								}
					}
					{
					if (TargetHasDebuff("Immolate"))
						if (CastSpell("Conflagrate")==true);
					}
					{
					if (TargetDebuffTimeLeft("Corruption")<2 && !_corruption.IsRunning)
						{
						if (CastSpell("Corruption")==true)
						_corruption.Start();
						}
					}
					{
					if (IsTargetBoss() && Me.CurrentTarget.HealthPercent > 20 && !TargetHasDebuff("Bane of Doom") && !_doom.IsRunning)
						{
						if (CastSpell("Bane of Doom")==true)
						_doom.Start();
						}
					}
					{
					if (IsTargetBoss() && Me.CurrentTarget.HealthPercent < 20 && TargetDebuffTimeLeft("Bane of Agony") <2 && !_agony.IsRunning ||
					!IsTargetBoss() && !TargetHasDebuff("Bane of Agony") && !_agony.IsRunning)
						{
						if (CastSpell("Bane of Agony")==true)
						_agony.Start();
						}
					}
					{
					if (TargetHasDebuff("Bane of Doom") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption") ||
						TargetHasDebuff("Bane of Agony") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption"))
						if (CastSpell("Chaos Bolt"));
					}
					{
					if (TargetHasDebuff("Bane of Doom") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption") ||
						TargetHasDebuff("Bane of Agony") && TargetHasDebuff("Immolate") && TargetHasDebuff("Corruption"))
						if (CastSpell("Incinerate"));
					}
					{
					if (Me.ManaPercent < 30)
						if(CastSpell("Life Tap"));
					}

////////////////////////////////////////////Moving Rotation here /////////////////////////////////////////////////////////////////////////////////////////////////
					
					{
					if (Me.IsMoving == true)
						{
						Lua.DoString("RunMacroText('/cast Fel Flame');"); 	                     
						}
					}
					{
					if (Me.IsMoving==true && Me.ManaPercent < 70)
						if(CastSpell("Life Tap"));
					}
						

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            }                      
            
        }  
  
        #endregion

    }
}